package com.new1cloud.upload.server.service.bootstrap;

import com.new1cloud.upload.server.service.FileUploadService;
import com.new1cloud.upload.server.service.bootstrap.handler.FileUploadServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutorService;

@Component
public class FileUploadServer implements ApplicationRunner {
    protected final Logger log = LoggerFactory.getLogger(this.getClass());
    private final FileUploadService fileUploadService;
    private final ExecutorService myExecutorService;
    public FileUploadServer(FileUploadService fileUploadService, ExecutorService myExecutorService) {
        this.fileUploadService = fileUploadService;
        this.myExecutorService = myExecutorService;
    }

    public void run() throws Exception {
        //cpu核心数
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup(availableProcessors * 2 - 2);
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ChannelPipeline p = ch.pipeline();
                        p.addLast(new LengthFieldPrepender(4));
                        p.addLast(new ObjectEncoder());
                        p.addLast(new LengthFieldBasedFrameDecoder(200 * 1024 * 1024, 0, 4, 0, 4));
                        p.addLast(new ObjectDecoder(200 * 1024 * 1024, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
//                        p.addLast(new FileUploadBasicInfoHandler(fileUploadService));
                        p.addLast(new FileUploadServerHandler(fileUploadService, myExecutorService));
                    }
                });

            ChannelFuture f = b.bind(17080).sync();
            log.info("文件上传服务端已正常启动....");
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        run();
    }
}
